#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#define RUN_ID_BYTES  (sizeof(uint64_t))
#define COUNTER_BYTES (sizeof(uint32_t))
#define KEY_BITS      256
#define IV_BYTES      12
#define TAG_BYTES     16

#define MSG_OVERHEAD (RUN_ID_BYTES + COUNTER_BYTES + IV_BYTES + TAG_BYTES)

typedef struct ESugGhzChatCryptoCtx ESubGhzChatCryptoCtx;

void crypto_init(void);

/* Function to clear sensitive memory. */
void crypto_explicit_bzero(void* s, size_t len);

ESubGhzChatCryptoCtx* crypto_ctx_alloc(void);
void crypto_ctx_free(ESubGhzChatCryptoCtx* ctx);

void crypto_ctx_clear(ESubGhzChatCryptoCtx* ctx);

bool crypto_ctx_set_key(
    ESubGhzChatCryptoCtx* ctx,
    const uint8_t* key,
    FuriString* flipper_name,
    uint32_t tick);
void crypto_ctx_get_key(ESubGhzChatCryptoCtx* ctx, uint8_t* key);

bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, uint8_t* out);
bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, uint8_t* out);

typedef bool (*CryptoCtxReplayDictWriter)(uint64_t run_id, uint32_t counter, void* context);
typedef bool (*CryptoCtxReplayDictReader)(uint64_t* run_id, uint32_t* counter, void* context);

size_t crypto_ctx_dump_replay_dict(
    ESubGhzChatCryptoCtx* ctx,
    CryptoCtxReplayDictWriter writer,
    void* writer_ctx);
size_t crypto_ctx_read_replay_dict(
    ESubGhzChatCryptoCtx* ctx,
    CryptoCtxReplayDictReader reader,
    void* reader_ctx);

#ifdef __cplusplus
}
#endif
